// params.cpp
// SQL Server Parameter class; retrieves parameters from SQL Server
//
// Methods:
//		params()					Default constructor
//		~params()					Custom destructor releases data pointer
//		static int getparamcount()	Retrieves number of SQL Server parameters passed in
//		static void getparam()		Retrieves specified parameter from SQL Server
// Properties:
//		SRVRETCODE success			Set to FAIL if retrieving parameter failed, SUCCESS
//									if it was successful
//		ULONG length				The actual length of the data passed in the parameter
//		ULONG maxlength				The max length of the parameter passed in
//		BYTE *cdata					The BYTE pointer to the character data passed in
//		BOOL isnull					Set to TRUE if SQL NULL is passed in; FALSE if parameter
//									is not SQL NULL
//		BYTE type					The type of the parameter
//
// Michael Coles, MCDBA
// 7/2005
//
#include "stdafx.h"
#include "params.h"
// getparamcount()
//
// This little routine retrieves the total number of parameters passed in to us.
// Always call this before calling getparam, to ensure that we are not trying to
// retrieve more parameters than were passsed in.
//
// Parameters:
//		SRV_PROC *srvproc	Server process pointer
// Returns:
//		int					Number of parameters passed in to from SQL Server
//
int params::getparamcount(SRV_PROC *srvproc) {
	return (srv_rpcparams(srvproc));
}
// getparam()
//
// This handy little routine retrieves the specified parameter.  For some reason, 
// SQL numbers parameters beginning with 1, not C-standard 0 as we might expect.
//
// Parameters:
//		SRV_PROC *srvproc	Server process pointer
//		int paramnum		Number of the SQL Server parameter to retrieve
//		params *p			Pointer to a params object
//
void params::getparam(SRV_PROC *srvproc, int paramnum, params *p) {
	// Set the success/failure code
	SRVRETCODE rc = SUCCEED;
	// Get the parameter length first
	rc = srv_paraminfo(srvproc, paramnum, &p->type, &p->maxlength, &p->length, NULL, &p->isnull);
	if (rc == SUCCEED) 
	{
		// Now we reserve the required space, +1 extra byte for a '\0' string end marker.
		p->cdata = new BYTE[p->length + 1];
		// Now we retrieve the actual parameter value.
		rc = srv_paraminfo(srvproc, paramnum, &p->type, &p->maxlength, &p->length, p->cdata, &p->isnull);
		if (rc == SUCCEED)
		{
			// We put a '\0' marker at the end, in case it's a string; although we already have
			// the length, this comes in handy should we want to manipulate the parameter value
			// as a '\0'-terminated C-string right out the box; by printing it for instance.
			*(p->cdata + p->length) = 0;
			// Now we figure out if this is an input or output parameter.
		}
		p->isoutput = (srv_paramstatus(srvproc, paramnum) & SRV_PARAMRETURN);
	}
	p->success = rc;
}
// ~params()
//
// This destructor will release the cdata array of dynamically allocated memory.
//
params::~params() {
	// Only if it was assigned.
	if (this->cdata != NULL) {
		delete [] this->cdata;
	}
}